package com.github.gaojh.server.handler;

import com.github.gaojh.server.http.HttpContext;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

/**
 * @author 高建华
 * @date 2019-03-30 22:40
 */
@Slf4j
public class HttpServerHandler extends ChannelInboundHandlerAdapter {

    private DispatcherHandler dispatcherHandler = new DispatcherHandler();

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        if (msg instanceof FullHttpRequest) {
            FullHttpRequest fullHttpRequest = (FullHttpRequest) msg;
            HttpContext httpContext = dispatcherHandler.buildHttpContext(ctx, fullHttpRequest);
            Executor executor = ctx.executor();
            CompletableFuture<HttpContext> future = CompletableFuture.completedFuture(httpContext);
            future.thenApplyAsync(dispatcherHandler::checkStaticResource, executor)
                    .thenApplyAsync(dispatcherHandler::handleInterceptorBefore,executor)
                    .thenApplyAsync(dispatcherHandler::invokeRoute, executor)
                    .thenApplyAsync(dispatcherHandler::handleInterceptorAfter,executor)
                    .thenApplyAsync(dispatcherHandler::buildResponse, executor)
                    .exceptionally(BuildResponse::buildErrorResponse)
                    .thenAcceptAsync(m -> dispatcherHandler.writeResponse(ctx, future, m), ctx.channel().eventLoop());
        } else {
            ReferenceCountUtil.release(msg);
        }

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
    }
}
